package com.ceac.kronos.ejb.entitybeans;

import com.ceac.kronos.ejb.entitybeans.Category;
import com.ceac.kronos.ejb.entitybeans.Checkpoint;
import com.ceac.kronos.ejb.entitybeans.Participant;

import java.io.Serializable;

import java.sql.Timestamp;

import java.util.Date;
import java.util.List;

import java.util.Vector;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.UniqueConstraint;

@Entity
@NamedQueries( { @NamedQuery(name = "Race.findAll", query = "select o from Race o"),
        @NamedQuery(name = "Race.findByName", query = "select o from Race o where o.edition=:edition and o.name=:name"),
        @NamedQuery(name = "Race.findById", query = "select o from Race o where o.raceId=:raceId") })
@Table(name = "RACES")
public class Race implements Serializable {
    @Column(name="ACTUAL_START_TIME")
    private Timestamp actualStartTime;
    @Column(name="CREATED_BY")
    private Integer createdBy;
    @Column(name="CREATION_DATE")
    private Timestamp creationDate;
    private String description;
    @Column(nullable = false)
    private Float distance;
    @Column(name="END_TIME")
    private Timestamp endTime;
    private Float laps;
    @Column(name="LAP_DISTANCE")
    private Float lapDistance;
    @Column(name="LAST_UPDATED_BY")
    private Integer lastUpdatedBy;
    @Column(name="LAST_UPDATE_DATE")
    private Timestamp lastUpdateDate;
    private String name;
    @Column(name="MAX_PARTICIPANTS")
    private Integer maxParticipants;
    @Id
    @Column(name="RACE_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.TABLE)
    @TableGenerator(name="RaceSequence", table="SEQUENCES",
        schema = "kronos", initialValue = 1, allocationSize = 1,
                    pkColumnName="SEQUENCE_NAME", valueColumnName = "SEQUENCE_COUNT", pkColumnValue="DEFAULT")
    private Integer raceId;
    @Column(name="START_TIME")
    private Timestamp startTime;
    private String surface;
    @Column(name="BIBS_RANGE_FROM")
    private int startBibsNumber;
    @Column(name="BIBS_RANGE_TO")
    private int endBibsNumber;
    @Column(name="LAST_ASSIGNED_BIBS_NUMBER")
    private int lastAssignedBibsNumber;
    @Column(name="REUSE_BIBS_NUMBER")
    private boolean reuseBibsNumbers;
    
    @OneToMany(targetEntity = Participant.class, mappedBy = "race", fetch = FetchType.LAZY)
    @OrderBy(value = "participantId")
    @JoinColumn(name = "RACE_ID", referencedColumnName = "RACE_ID")
    private List<Participant> participants;

    @OneToMany(targetEntity = Checkpoint.class, mappedBy = "race")
    private List<Checkpoint> checkpoints;

    @OneToOne(targetEntity = Edition.class)
    @JoinColumn(name = "EDITION_ID", referencedColumnName = "EDITION_ID")
    private Edition edition;

    @ManyToMany(targetEntity = Category.class)
    @JoinTable(name = "RACE_CATEGORIES", schema = "kronos",
               joinColumns = { @JoinColumn(name = "RACE_ID",
                    referencedColumnName = "RACE_ID") },
        inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID",
                    referencedColumnName = "CATEGORY_ID") },
        uniqueConstraints = { @UniqueConstraint(columnNames = { "CATEGORY_ID", "RACE_ID" }) })
    private List<Category> categories;
    
    public Race() {
      this.participants = new Vector<Participant>();
      this.checkpoints = new Vector<Checkpoint>();
      this.categories = new Vector<Category>();
      this.setCreationDate(new Timestamp((new Date()).getTime()));
      this.setCreatedBy(0);
    }

    public Timestamp getActualStartTime() {
        return actualStartTime;
    }

    public void setActualStartTime(Timestamp actualStartTime) {
        this.actualStartTime = actualStartTime;
    }

    public Integer getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
    }

    public Timestamp getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Timestamp creationDate) {
        this.creationDate = creationDate;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Float getDistance() {
        return distance;
    }

    public void setDistance(Float distance) {
        this.distance = distance;
    }

    public Timestamp getEndTime() {
        return endTime;
    }

    public void setEndTime(Timestamp endTime) {
        this.endTime = endTime;
    }

    public Float getLaps() {
        return laps;
    }

    public void setLaps(Float laps) {
        this.laps = laps;
    }

    public Float getLapDistance() {
        return lapDistance;
    }

    public void setLapDistance(Float lapDistance) {
        this.lapDistance = lapDistance;
    }

    public Integer getLastUpdatedBy() {
        return lastUpdatedBy;
    }

    public void setLastUpdatedBy(Integer lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    }

    public Timestamp getLastUpdateDate() {
        return lastUpdateDate;
    }

    public void setLastUpdateDate(Timestamp lastUpdateDate) {
        this.lastUpdateDate = lastUpdateDate;
    }

    public Integer getMaxParticipants() {
        return maxParticipants;
    }

    public void setMaxParticipants(Integer maxParticipants) {
        this.maxParticipants = maxParticipants;
    }

    public Integer getRaceId() {
        return raceId;
    }

    public void setRaceId(Integer raceId) {
        this.raceId = raceId;
    }

    public Timestamp getStartTime() {
        return startTime;
    }

    public void setStartTime(Timestamp startTime) {
        this.startTime = startTime;
    }

    public String getSurface() {
        return surface;
    }

    public void setSurface(String surface) {
        this.surface = surface;
    }

    public void setParticipants(List<Participant> participants) {
        this.participants = participants;
    }

    public List getParticipants() {
        return participants;
    }
    
    public void addParticipant(Participant aParticipant) {
        this.participants.add(aParticipant);
        aParticipant.setRace(this);
    }

    public void setCheckpoints(List<Checkpoint> checkpoints) {
        this.checkpoints = checkpoints;
    }

    public List<Checkpoint> getCheckpoints() {
        return checkpoints;
    }

    public void setEdition(Edition edition) {
        this.edition = edition;
    }

    public Edition getEdition() {
        return edition;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setStartBibsNumber(int startBibsNumber) {
        this.startBibsNumber = startBibsNumber;
    }

    public int getStartBibsNumber() {
        return startBibsNumber;
    }

    public void setEndBibsNumber(int endBibsNumber) {
        this.endBibsNumber = endBibsNumber;
    }

    public int getEndBibsNumber() {
        return endBibsNumber;
    }

    public void setLastAssignedBibsNumber(int lastAssignedBibsNumber) {
        this.lastAssignedBibsNumber = lastAssignedBibsNumber;
    }

    public int getLastAssignedBibsNumber() {
        return lastAssignedBibsNumber;
    }

    public void setReuseBibsNumbers(boolean reuseBibsNumbers) {
        this.reuseBibsNumbers = reuseBibsNumbers;
    }

    public boolean isReuseBibsNumbers() {
        return reuseBibsNumbers;
    }

    public void setCategories(List<Category> categories) {
        this.categories = categories;
    }

    public List<Category> getCategories() {
        return categories;
    }
}
